package com.eightywork.life.imageCache;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.widget.ImageView;

public class LocalImageLoader {
	private ExecutorService executorService;
	private int width;
	private int height;
	MemoryCache memoryCache = new MemoryCache();
	private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
	public interface onLoadingFinishListener{
		void onFinish(Bitmap bitmap, ImageView imageView);
	};
	
	public onLoadingFinishListener onLoadingFinishListener;
	
	public LocalImageLoader() {
		executorService = Executors.newFixedThreadPool(5);
	}
	
	public void DisplayImage(String path, int width, int height, ImageView imageView){
		this.width = width;
		this.height = height;
		imageViews.put(imageView, path);
		Bitmap bitmap = memoryCache.get(path);
		if (bitmap != null){
			imageView.setImageBitmap(bitmap);
		}
		else {
			queuePhoto(path, imageView);
			imageView.setVisibility(View.INVISIBLE);
		}
	}
	
	public void DisplayImage(String path, int width, int height, ImageView imageView, Bitmap defaultBitmap){
		this.width = width;
		this.height = height;
		imageViews.put(imageView, path);
		Bitmap bitmap = memoryCache.get(path);
		if (bitmap != null){
			imageView.setImageBitmap(bitmap);
		}
		else {
			imageView.setImageBitmap(defaultBitmap);
			queuePhoto(path, imageView);
		}
	}
	
	public void DisplayImage(String path, int width, int height, ImageView imageView, onLoadingFinishListener onLoadingFinishListener){
		this.width = width;
		this.height = height;
		this.onLoadingFinishListener = onLoadingFinishListener;
		imageViews.put(imageView, path);
		Bitmap bitmap = memoryCache.get(path);
		if (bitmap != null){
			imageView.setImageBitmap(bitmap);
		}
		else {
			imageView.setVisibility(View.INVISIBLE);
		}
	}
	
	private void queuePhoto(String path, ImageView imageView) {
		PhotoToLoad p = new PhotoToLoad(path, imageView);
		executorService.submit(new PhotosLoader(p));
	}
	private class PhotoToLoad {
		public String path;
		public ImageView imageView;

		public PhotoToLoad(String u, ImageView i) {
			path = u;
			imageView = i;
		}
	}

	class PhotosLoader implements Runnable {
		PhotoToLoad photoToLoad;

		PhotosLoader(PhotoToLoad photoToLoad) {
			this.photoToLoad = photoToLoad;
		}

		@Override
		public void run() {
			if (imageViewReused(photoToLoad))
				return;
			Bitmap bmp = getBitmap(photoToLoad.path);
			memoryCache.put(photoToLoad.path, bmp);
			// 如果线程关闭不再更新UI
			if(!executorService.isShutdown()){
				if (imageViewReused(photoToLoad))
					return;
				BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
				// 更新的操作放在UI线程中
				Activity a = (Activity) photoToLoad.imageView.getContext();
				a.runOnUiThread(bd);
			}
		}
	}
	
	private Bitmap getBitmap(String path) {
		File f = new File(path);
		return decodeFile(f);
	}
	private Bitmap decodeFile(File f) {
		try {
			// decode image size
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(new FileInputStream(f), null, o);

			// Find the correct scale value. It should be the power of 2.
			
			int width_tmp = o.outWidth, height_tmp = o.outHeight;
			int scale = 1;
			if(width != 0 && height != 0){
				while (true) {
					if (width_tmp / 2 < width
							|| height_tmp / 2 < height)
						break;
					width_tmp /= 2;
					height_tmp /= 2;
					scale *= 2;
				}
			}

			// decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inSampleSize = scale;
			return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	boolean imageViewReused(PhotoToLoad photoToLoad) {
		String tag = imageViews.get(photoToLoad.imageView);
		if (tag == null || !tag.equals(photoToLoad.path))
			return true;
		return false;
	}
	
	// 用于在UI线程中更新界面
	class BitmapDisplayer implements Runnable {
		Bitmap bitmap;
		PhotoToLoad photoToLoad;

		public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
			bitmap = b;
			photoToLoad = p;
		}

		public void run() {
			if (imageViewReused(photoToLoad))
				return;
			if (bitmap != null){
				if(onLoadingFinishListener != null){
					onLoadingFinishListener.onFinish(bitmap,photoToLoad.imageView);
					return;
				}
				photoToLoad.imageView.setImageBitmap(bitmap);
				photoToLoad.imageView.setVisibility(View.VISIBLE);
			}
			else
				photoToLoad.imageView.setVisibility(View.INVISIBLE);
		}
	}
}
